package com.cms.support;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import sun.misc.BASE64Decoder;

public class Uploader {

	private String url = "";
	private String fileName = "";
	private String state = "";
	private String type = "";
	private String originalName = "";
	private long size = 0L;
	private HttpServletRequest request = null;
	private String title = "";
	private String savePath = "upload";
	private String[] allowFiles = { ".rar", ".doc", ".docx", ".zip", ".pdf",
			".txt", ".swf", ".wmv", ".gif", ".png", ".jpg", ".jpeg", ".bmp" };
	private int maxSize = 10000;
	private HashMap<String, String> errorInfo = new HashMap<String, String>();

	public Uploader() {

	}

	public Uploader(HttpServletRequest request) {
		this.request = request;
		HashMap<String, String> tmp = this.errorInfo;
		tmp.put("SUCCESS", "SUCCESS");
		tmp.put("NOFILE", "未包含文件上传域");
		tmp.put("TYPE", "不允许的文件格式");
		tmp.put("SIZE", "文件大小超出限制");
		tmp.put("ENTYPE", "请求类型ENTYPE错误");
		tmp.put("REQUEST", "上传请求异常");
		tmp.put("IO", "IO异常");
		tmp.put("DIR", "目录创建失败");
		tmp.put("UNKNOWN", "未知错误");
	}

	public void upload() throws Exception {
		boolean isMultipart = ServletFileUpload
				.isMultipartContent(this.request);
		if (!(isMultipart)) {
			this.state = ((String) this.errorInfo.get("NOFILE"));
			return;
		}
		try {
			MultipartResolver resolver = new CommonsMultipartResolver(
					this.request.getSession().getServletContext());
			MultipartHttpServletRequest multipartRequest = resolver
					.resolveMultipart(request);
			CommonsMultipartFile orginalFile = (CommonsMultipartFile) multipartRequest
					.getFile("upfile");

			this.originalName = orginalFile.getOriginalFilename();
			if (!this.checkFileType(this.originalName)) {
				this.state = this.errorInfo.get("TYPE");
				return;
			}
			this.type = this.getFileExt(this.originalName);
			this.size = orginalFile.getSize();

			this.url = QiniuFileUtil.upload(orginalFile);
			this.state = this.errorInfo.get("SUCCESS");
		} catch (Exception e) {
			this.state = this.errorInfo.get("UNKNOWN");
		}
	}

	public void uploadBase64(String fieldName) {
		String savePath = getFolder(this.savePath);
		String base64Data = this.request.getParameter(fieldName);
		this.fileName = getName("test.png");
		this.url = savePath + "/" + this.fileName;
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			File outFile = new File(getPhysicalPath(this.url));
			OutputStream ro = new FileOutputStream(outFile);
			byte[] b = decoder.decodeBuffer(base64Data);
			for (int i = 0; i < b.length; ++i)
				if (b[i] < 0) {
					int tmp124_122 = i;
					byte[] tmp124_120 = b;
					tmp124_120[tmp124_122] = (byte) (tmp124_120[tmp124_122] + 256);
				}

			ro.write(b);
			ro.flush();
			ro.close();
			this.state = ((String) this.errorInfo.get("SUCCESS"));
		} catch (Exception e) {
			this.state = ((String) this.errorInfo.get("IO"));
		}
	}

	private boolean checkFileType(String fileName) {
		Iterator<String> type = Arrays.asList(this.allowFiles).iterator();
		while (type.hasNext()) {
			String ext = (String) type.next();
			if (fileName.toLowerCase().endsWith(ext))
				return true;
		}

		return false;
	}

	private String getFileExt(String fileName) {
		return fileName.substring(fileName.lastIndexOf("."));
	}

	private String getName(String fileName) {
		Random random = new Random();
		return (this.fileName = random.nextInt(10000)
				+ System.currentTimeMillis() + getFileExt(fileName));
	}

	private String getFolder(String path) {
		SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
		path = path + "/" + formater.format(new Date());
		File dir = new File(getPhysicalPath(path));
		if (!(dir.exists()))
			try {
				dir.mkdirs();
			} catch (Exception e) {
				this.state = ((String) this.errorInfo.get("DIR"));
				return "";
			}

		return path;
	}

	private String getPhysicalPath(String path) {
		String servletPath = this.request.getServletPath();
		String realPath = this.request.getSession().getServletContext()
				.getRealPath(servletPath);
		return new File(realPath).getParent() + "/" + path;
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public void setAllowFiles(String[] allowFiles) {
		this.allowFiles = allowFiles;
	}

	public void setMaxSize(int size) {
		this.maxSize = size;
	}

	public long getSize() {
		return this.size;
	}

	public String getUrl() {
		return this.url;
	}

	public String getFileName() {
		return this.fileName;
	}

	public String getState() {
		return this.state;
	}

	public String getTitle() {
		return this.title;
	}

	public String getType() {
		return this.type;
	}

	public String getOriginalName() {
		return this.originalName;
	}

	public static final byte[] input2byte(InputStream inStream)
			throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		byte[] in2b = swapStream.toByteArray();
		return in2b;
	}
}
